package cn.stylefeng.guns.sys.modular.system.service;

import cn.stylefeng.guns.sys.core.upay.constant.PayConstant;
import cn.stylefeng.guns.sys.core.upay.exception.UpayException;
import cn.stylefeng.guns.sys.core.upay.request.transaction.PayRequestBody;
import cn.stylefeng.guns.sys.core.upay.request.transaction.PreCreateRequestBody;
import cn.stylefeng.guns.sys.core.upay.response.PayResponseBody;
import cn.stylefeng.guns.sys.core.upay.response.UpayRequest;
import cn.stylefeng.guns.sys.core.upay.response.UpayResponse;
import cn.stylefeng.guns.sys.core.upay.utils.DateUtils;
import cn.stylefeng.guns.sys.core.upay.utils.StringUtils;
import cn.stylefeng.guns.sys.modular.api.controller.BaseOperate;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class UPayService {
    private final static Logger LOGGER = LoggerFactory.getLogger(UPayService.class);

    public Map<String, Object> pay(String amount, String extNo) {
        Map<String, Object> resultMap = new HashMap<>(16);
        // 商户订单号
        if (StringUtils.isEmpty(extNo)) {
            extNo = DateUtils.formatNow(DateUtils.YYYYMMDDHHMMSS + DateUtils.SSSS);
        }
        String requestId = DateUtils.formatNow(DateUtils.YYYYMMDDHHMMSS + DateUtils.SSSS);
        PreCreateRequestBody ctx = new PreCreateRequestBody();
        ctx.setExt_no(extNo);
        // 交易金额，元为单位
        ctx.setTotal_amount(amount);
        ctx.setSubject(PayConstant.PAY_SUBJECT);
        ctx.setQr_code_enable(PayConstant.QR_CODE_ENABLE_Y);
        /**
         * 在真正的工程目录开发中，这里以下的公共代码可以提取到基类中去
         * 具体情况开发者可以跟句情况做相应的改变
         */
        UpayRequest request = new UpayRequest();
        request.setMerchant_id(PayConstant.MERCHANT_ID);
        request.setRequest_id(requestId);
        // 时间戳
        request.setTimestamp(DateUtils.formatNow(DateUtils.YYYY_MM_DD_HH_MM_SS));
        // 终端号
        request.setTerminal_id(PayConstant.TERMINAL_ID);
        // 支付渠道
        request.setBiz_channel(ctx.acquireBizChannel());
        // 交易类型
        request.setBiz_type(ctx.acquireBizType());
        request.setApp_info(PayConstant.APP_INFO);
        request.setSign_type(PayConstant.SIGN_TYPE_MD5);
        request.setVersion(PayConstant.VERSION);

        request.setBiz_content(ctx.toString());

        String privateKey = PayConstant.MD5_KEY;
        String publicKey = null;

        /**
         * 目前对于平台开发者，为简便，统一使用MD5的方式进行签名
         * 这里只是提供了一种使用RSA签名的兼容性参考
         */
        if (PayConstant.SIGN_TYPE_RSA.equalsIgnoreCase(request.getSign_type())) {
            privateKey = BaseOperate.getKey("private_key.pem");
            publicKey  = BaseOperate.getKey("public_key.pem");
        }

        UpayResponse response;
        try {
            response = BaseOperate.client.execute(request, privateKey, publicKey, PayConstant.SERVER_URL_TEST);
        } catch (UpayException e) {
            resultMap.put("code", "error");
            resultMap.put("msg", "支付失败");
            LOGGER.error("支付出错啦:", e);
            return resultMap;
        }

        /**
         * 这里返回的biz_content是String类型的数据，但其格式符合JSON格式
         * 开发者根据需要，将biz_content提出来，转换为一个Class对象
         */
        LOGGER.info("接口返回response:{}", JSON.toJSONString(response, SerializerFeature.PrettyFormat));

        PayResponseBody body = JSON.parseObject(response.getBiz_content(), PayResponseBody.class);

        LOGGER.info("返回的biz_content:{}", JSON.toJSONString(body, SerializerFeature.PrettyFormat));
        resultMap.put("code", "success");
        resultMap.put("msg", "支付成功");
        resultMap.put("data", response);
        return resultMap;
    }
}
